/*
 * @Author: hongbin
 * @Date: 2023-06-23 21:23:42
 * @LastEditors: hongbin
 * @LastEditTime: 2023-08-08 22:06:41
 * @Description: noise background
 */
import { FC } from "react";
import * as THREE from "three";
import { ThreeHelper } from "@/ThreeHelper";
import Layout from "@/components/Three/Layout";

interface IProps {}

const destroyEvent = [] as VoidFunction[];

const Index: FC<IProps> = () => {
    return (
        <Layout
            seoTitle={"噪音背景"}
            init={init}
            destroy={() => destroyEvent.forEach((destroy) => destroy())}
        />
    );
};

export default Index;

async function init(helper: ThreeHelper) {
    helper.addStats();
    helper.frameByFrame();
    helper.addGUI();
    helper.addAxis();
    helper.useRoomEnvironment();
    helper.setBackground("#7d7866");

    helper.camera.position.set(0, 0, 10);

    const noiseBg = new NoiseBg(helper.camera);
    helper.add(noiseBg.mesh);

    // const angle = (helper.camera.fov / 2) * (Math.PI / 180);
    // const angle = THREE.MathUtils.degToRad(helper.camera.fov / 2);
    // const height = 2 * Math.tan(angle) * helper.camera.position.z;
    // const width = height * helper.camera.aspect;

    const box = new THREE.Mesh(
        new THREE.BoxGeometry(2, 2, 2),
        new THREE.MeshStandardMaterial()
    );

    helper.add(box);
}

export class NoiseBg {
    mesh: THREE.Mesh<THREE.PlaneGeometry, THREE.ShaderMaterial>;

    constructor(camera: THREE.PerspectiveCamera) {
        const material = this.material();
        const angle = THREE.MathUtils.degToRad(camera.fov / 2);
        const height = 2 * Math.tan(angle) * camera.position.z;
        const width = height * camera.aspect;

        this.mesh = new THREE.Mesh(
            new THREE.PlaneGeometry(width, height),
            material
        );

        this.mesh.onAfterRender = () => {
            material.uniforms.iTime.value += 0.01;
        };
    }

    material() {
        const material = new THREE.ShaderMaterial({
            uniforms: { iTime: { value: 1 } },
            transparent: true,
            vertexShader: `
            varying vec2 vUv;

            void main() {
                vUv = uv;
                vec4 viewPosition = vec4(position, 1.0);
                gl_Position =  viewPosition;
            }`,
            fragmentShader: `
            uniform float iTime;
            varying vec2 vUv;
            #include <common>
           
            void main() {
            
                vec3 color = vec3(rand(vUv * iTime));
                gl_FragColor = vec4(color, 0.2);
            }`,
        });

        return material;
    }
}
